#pragma once

#include "Sock.hpp"
#include "Log.hpp"
#include "Protocol.hpp"
#include "NetIO.hpp"
#include <unistd.h>

namespace ns_tcpclient
{
    class Client
    {
#define SIZE 1024

    public:
        Client(const std::string &ip, uint16_t port)
            : _cli_sock(-1), _ip(ip), _port(port)
        {
        }

        void init()
        {
            // 客户端初始化

            // 1. 创建网络套接字文件描述符
            _cli_sock = _sock.Socket();
            if (_cli_sock < 0)
            {
                std::cout << "socket fail" << std::endl;
                exit(2);
            }

            // 2. 客户端连接服务器
            if (_sock.Connect(_cli_sock, _ip, _port) < 0)
            {
                std::cout << "connect error" << std::endl;
                exit(3);
            }
            logMessage(NORMAL, "Client Init success!\n");
        }

        // 运行客户端程序
        void start()
        {
            // 客户端要向服务器发送请求

            // std::string calExpress;    // 读取用户输入的运算表达式
            std::string recv_msg;     // 存放客户端从服务器读取数据的缓冲区
            ns_protocol::Reponse rep; // 存放反序列化后的计算结果

            while (true)
            {
                std::cout << "请输入运算式# " << std::flush;
                // std::getline(std::cin, calExpress);
                ns_protocol::Request req;
                std::cin >> req._x >> req._op >> req._y;

                // 序列化数据 + 发送
                std::string serReq = req.serialize();                   // 序列化客户端请求
                std::cout << "序列化运算式: " << serReq << std::endl;
                std::string serReqEnCode = ns_protocol::EnCode(serReq); // 编码 -- length/r/n_x _op _y/r/n

                bool ret = ns_netio::Send(_cli_sock, serReqEnCode);
                if (!ret)
                    continue;

                // ssize_t n = send(_cli_sock, serReq.c_str(), serReq.size(), 0);   // 发送数据
                // if(n < 0)
                // {
                //     logMessage(ERROR, "Client# send message error\n");
                //     continue;
                // }
                // logMessage(NORMAL, "Client# send message success\n");

                // 从服务器中读回数据
                while (true)
                {
                    ret = ns_netio::Recv(_cli_sock, recv_msg);
                    if (!ret)
                        break;

                    std::string deResult = ns_protocol::DeCode(recv_msg);
                    if(deResult.empty()) continue;

                    logMessage(NORMAL, "decode result success: %s\n", deResult.c_str());

                    bool flag = rep.deserialize(deResult);
                    if (flag)
                    {
                        if (rep._flag == 0)
                            std::cout << "Get right result: " << rep._result << std::endl;
                        else
                            std::cout << "something wrong when caculate, flag:" << rep._flag << std::endl;
                    }

                    break;
                }
            }
        }

    private:
        ns_sock::Sock _sock;
        int _cli_sock;   // 套接字文件描述符
        std::string _ip; // 服务器网络IP地址
        uint16_t _port;  // 端口号
    };
}